﻿#include "EventTrigger.h"
#include"HttpClient.h"
#include "../com/lib_json/src/json.h"
#include"convert.h"
extern EventTrigger g_eventTrigger;
const char* LuaTable2Json(lua_State *ls)
{
	void * table=NULL;
	const char* error=NULL,*json_str=NULL;
	int result=0;
	lua_getglobal(ls,"cjson");
	lua_getfield(ls,-1,"encode");
	lua_pushvalue(ls,-3);
	result=lua_pcall(ls,1,1,0);
	CHECK_RESULT(ls);
	if(lua_type(ls,-1)!=LUA_TSTRING)
	{
         PRINTLN("invalid object can't decode");
		//cout<<lua_tostring(ls,-1)<<endl;
	}
	json_str=lua_tostring(ls,-1);
	//清空堆栈
	lua_settop(ls,0);
    return json_str;
}


int closeNotify(lua_State *ls)
{
	const char* url=lua_tostring(ls,1);
	if(strlen(url)>=0)
	{
		HttpClient *client=HttpClient::Instance();
		cout<<url<<endl;
		std::string res=client->getContent(url);
		cout<<res<<endl;
	}
	return 1;
}




// C接口 - 网络发送
int CNetSend(lua_State *ls)
{
	// 获得socket
	int socket = lua_tointeger(ls,1);
	unsigned int data_len=0;
	char head[4]={0};

	const char* data=NULL; 


	// 获得发送字符串
	//const char* data = lua_tostring(ls,2);
    data=LuaTable2Json(ls);
	
    data_len=strlen(data);

#ifdef _DEBUG
	//PRINTLN(g_eventTrigger.m_systemKey.c_str());
	//PRINTLN(data);
    
    //cout<<data_len<<endl;
    //发送前加密
	//EN(const_cast<char*>(data),data_len,g_eventTrigger.m_systemKey.c_str(),g_eventTrigger.m_ifactor);
 /*   
    DE(const_cast<char*>(data),data_len,g_eventTrigger.m_systemKey.c_str(),g_eventTrigger.m_ifactor);

    PRINTLN(data);
    EN(const_cast<char*>(data),data_len,g_eventTrigger.m_systemKey.c_str(),g_eventTrigger.m_ifactor);
    */
#endif

	if(data==NULL)
	{
		PRINTLN("Invalid Object When Send");
		lua_pushinteger(ls,0);
		return 1;
	}else
	{
	     
		  head[0]=data_len>>24&0xFF;
		  head[1]=data_len>>16&0xFF;
		  head[2]=data_len>>8&0xFF;
		  head[3]=data_len&0xFF;
		PRINTLN("send data to:"<<socket<<" len "<<data_len<< " data:"<<data);
	}
	//const char* data = lua_tostring(ls,2);
	int totalSendSize = 0;
	int thisSendSize = 0;

	// 如果包结束符是0,即lua调用CNetSend时不用带结束符,因为字符串的结束符就是0,否之则要
	#if C_ED_ == '\x00'
		const int dataLen = data_len + 1;
	#else
		const int dataLen = data_len;
	#endif

	const char* buf = data;
	::send(socket,head,4,0);
	do {
		if((thisSendSize = ::send(socket,buf,dataLen - totalSendSize,0)) == SOCKET_ERROR)
		{
			PRINT_ERROR("Send Failed:"<< data);
			break;
		}
		totalSendSize += thisSendSize;	//累加发送数据
		buf += thisSendSize;			//移动指针发送末发送的内容
	} while(totalSendSize < dataLen);

	// 返回发送出去的字符串
	lua_pushinteger(ls,totalSendSize);
	return 1;
}
// C接口 - 根据1970年来返回的毫秒数
int CGetTime(lua_State *ls)
{
#if defined(WIN32)
	struct _timeb t;
	_ftime(&t);
	lua_pushnumber(ls,t.time * 1000 + t.millitm);
#else
	struct timeb t;
	ftime(&t);
	lua_pushnumber(ls,t.time * 1000 + t.millitm);
#endif
	return 1;
}

int CNetClose(lua_State *ls)
{
	int socket_id=lua_tointeger(ls,1);
	//string a(data);
	//const char* b = md5(a).c_str();
	//string ss=md5(a);
	//const char* b=ss.c_str();
	//lua_pushstring(ls,b);
	if(socket_id)
	{
#ifdef _WIN32
		closesocket(socket_id);
#elif  defined(__linux__)
		close(socket_id);
#endif
	}
	return 1;
}

int errorhandler(lua_State *L)
{
	printf("%s",lua_tostring(L,-1));
	lua_pop(L,1);
	return 1;
}

//C md5
int  CMd5(lua_State *ls)
{
	const char* data = lua_tostring(ls,1);
	string a(data);
	//const char* b = md5(a).c_str();
    string ss=MD5STR(a);
	const char* b=ss.c_str();
	lua_pushstring(ls,b);
	return 1;
}

bool EventTrigger::open(const char* file,const char* systemKey,const char* adminKey,const char* filter,const char* tgwHeader,int wrong_count,const char *url,const char *logoutUrl,int ifactor,int world_chat_interval)
{
	// 加载主文件
	PRINT_ITEM("load file",file);
    m_File=file;
    m_systemKey=systemKey;
	m_filter=filter;
	m_tgwHeader=tgwHeader;
	m_iwong_count=wrong_count;
	m_black_list_url=url;
	m_logout_url=logoutUrl;
	m_ifactor=ifactor;
	m_admin_key=adminKey;
	 
	m_world_chat_interval=world_chat_interval;
	HttpClient *client=HttpClient::Instance();
	std::string black_users=client->getContent(url);
	//PRINTLN(m_File<<"here");
	// 扩展全局变量
	lua_pushstring(lcScript.pLs,_CB_);
	lua_setglobal(lcScript.pLs,"_CB_");
	lua_pushstring(lcScript.pLs,_EN_);
	lua_setglobal(lcScript.pLs,"_EN_");
	lua_pushstring(lcScript.pLs,_1_);
	lua_setglobal(lcScript.pLs,"_1_");
	lua_pushstring(lcScript.pLs,_2_);
	lua_setglobal(lcScript.pLs,"_2_");
	lua_pushstring(lcScript.pLs,_3_);
	lua_setglobal(lcScript.pLs,"_3_");
	lua_pushstring(lcScript.pLs,systemKey);
	lua_setglobal(lcScript.pLs,"systemKey");
	lua_pushstring(lcScript.pLs,adminKey);
	lua_setglobal(lcScript.pLs,"adminKey");
	lua_pushstring(lcScript.pLs,filter);
	lua_setglobal(lcScript.pLs,"filter");
	lua_pushstring(lcScript.pLs,tgwHeader);
	lua_setglobal(lcScript.pLs,"tgwHeader");
	lua_pushnumber(lcScript.pLs,wrong_count);
	lua_setglobal(lcScript.pLs,"wrongCount");
	lua_pushnumber(lcScript.pLs,world_chat_interval);
	lua_setglobal(lcScript.pLs,"worldChatInterval");
	lua_pushstring(lcScript.pLs,logoutUrl);
	lua_setglobal(lcScript.pLs,"logoutUrl");


	// 扩展接口
	lua_pushcfunction(lcScript.pLs,CNetSend);
	lua_setglobal(lcScript.pLs,"CNetSend");
	lua_pushcfunction(lcScript.pLs,CGetTime);
	lua_setglobal(lcScript.pLs,"CGetTime");
	lua_pushcfunction(lcScript.pLs,CMd5);
	lua_setglobal(lcScript.pLs,"CMd5");
	lua_pushcfunction(lcScript.pLs,CNetClose);
	lua_setglobal(lcScript.pLs,"CNetClose");
	lua_pushcfunction(lcScript.pLs,closeNotify);
	lua_setglobal(lcScript.pLs,"closeNotify");
	//lua_pushcfunction(lcScript.pLs,errorhandler);
	//lua_setglobal(lcScript.pLs,"errorHandler");


	// 加载脚本
	if(!lcScript.load(file))
		return false;

	// 调用初始化函数
	int err_no;
	if(lcScript.call(err_no,"OnInit"))
		return false;

	//lua_pushstring(lcScript.pLs,black_users.c_str());
	//cout<<black_users.c_str()<<endl;
	//cout<<black_users.length()<<endl;
	if(lcScript.call(err_no,"InitBlackList","%t",black_users.c_str()))
		return false;
	if(err_no)
		return false;
 
	return true;
}

bool EventTrigger::reload()
{
    PRINTLN("reload");
    lua_close(lcScript.pLs);
	lcScript.pLs=luaL_newstate();
	luaL_openlibs(lcScript.pLs);
	return open(m_File.c_str(),m_systemKey.c_str(),m_admin_key.c_str(),m_filter.c_str(),m_tgwHeader.c_str(),m_iwong_count,m_black_list_url.c_str(),m_logout_url.c_str(),m_ifactor,m_world_chat_interval);

}
//增加发送包错误次数
void wrong_pack_increment(int socket_id)
{
	map<int,int>::iterator it=g_wong_count.find(socket_id);
	if(it!=g_wong_count.end())
	{
		g_wong_count[socket_id]++;
	}

}

bool EventTrigger::touch(ANet& client,const char* package)
{

	PRINTLN("got data IP:" << client.get_ip()<<"\ndata:"<<package);
	// 调用函数
	int err_no=0;
	bool parse_ok=true;
	//Json::Reader reader(Json::Features::strictMode());
	//Json::Value root;
	//Json::FastWriter writer;
	
	const char *start=NULL,*end=NULL;
	char sep_pack[10240]={0};
	const char *p=package,*cp_start=package;
	const char *policy="<cross-domain-policy><site-control permitted-cross-domain-policies=\"all\"/><allow-access-from domain=\"*\" to-ports=\"*\"/></cross-domain-policy>";
    const char *attacker="who_are_you?";
	if(strncmp(package,"<policy-file-request/>",22)==0)
	{
		g_request_policy.insert(pair<int,int>(client.nSocket,1));
		//长度必须加1 不然flash 客户端不认 
		send(client.nSocket,policy,strlen(policy)+1,0);
		return true;
	}
#ifdef _DEBUG 
    //这里解密
	//DE(const_cast<char*>(package),client.wsaBuf.len,m_systemKey.c_str(),m_ifactor);
	//PRINTLN(package);
	//EN(const_cast<char*>(package),m_systemKey.c_str(),m_ifactor);
	//wstring wx=UTF8ToUnicode(package);

	//string ss=UnicodeToANSI(wx);
 //   cout<<ss<<endl;
 //   cout<<client.wsaBuf.len<<endl;
	//PRINTLN(package);
	//return TRUE;
#endif 
	//未请求策略文件直接发命令强制关掉
#ifdef _DEBUG
	//if(g_request_policy.find(client.nSocket)==g_request_policy.end())
	//{
	//	send(client.nSocket,attacker,strlen(attacker)+1,0);
	//	return false;
	//}
#endif
 //   if((end=(char*)strrchr(package,C_ED_))!=NULL)
	//{
 //       *++end=0;
	//}

	//if(lcScript.decode(err_no,package,"obj"))
	//{
	//	PRINTLN("WRONG JSON::"<<package);
	//	parse_ok=false;
	//	return true;
	//}
	//if(NULL!=(start=strchr(package,C_ST_)))
	//{
 //       p=start;
	//	cp_start=start;
	//}else{
	//	//没有开始标志
	//	PRINTLN("WRONGPACK NO START");
	//	wrong_pack_increment(client.nSocket);
	//	return true;
	//}
	//if(NULL!=(end=strrchr(package,C_ED_)))
	//{
	//	//去掉最后一个包后面的内容
 //       *(char*)(end+1)=0;
	//}else{
	//	//没有结束标志
	//	PRINTLN("WRONGPACK NO END");
	//	wrong_pack_increment(client.nSocket);
	//	return true;
	//}
 //   end=NULL;
	//最大连包数量
	int  max_pack=10;			    
	int try_pack=0;
	static const char SEP[]={C_EN_};
	char * token=strtok(const_cast<char*>(p),C_EN_);  

	while(token!=NULL&&try_pack<max_pack)
	{
		if(parse_ok&&lcScript.call(err_no,"OnCommand","%d%t%s",client.nSocket,token,client.get_ip()))
		   wrong_pack_increment(client.nSocket);
		token=strtok(NULL,C_EN_);
		++try_pack;									   
   //    end=strchr(p,C_ED_);
	  // //连包情况
	  // if(NULL!=end&&*(end+1)==C_ST_)
	  // {

		 //   memset(sep_pack,0,sizeof(sep_pack)/sizeof(char));
   //         strncpy(sep_pack,cp_start,end+1-cp_start);
			//if(parse_ok&&lcScript.call(err_no,"OnCommand","%d%t",client.nSocket,sep_pack))
			//	wrong_pack_increment(client.nSocket);
			//cp_start=end+1;
			//p=cp_start;
			//++try_pack;
	  // }else if(NULL!=end&&*(end+1)==0){
		 //   //最后一个包
   //         //PRINTLN(cp_start);
			//if(parse_ok&&lcScript.call(err_no,"OnCommand","%d%t",client.nSocket,cp_start))
			//	wrong_pack_increment(client.nSocket);
			//p=NULL;
			//++try_pack;
	  // }/*else if(NULL!=end&&*(end+1)!=','){
		 //  memset(sep_pack,0,sizeof(sep_pack)/sizeof(char));
		 //  strncpy(sep_pack,cp_start,end+1-cp_start);
		 //  if(parse_ok&&lcScript.call(err_no,"OnCommand","%d%t",client.nSocket,sep_pack))
			//   wrong_pack_increment(client.nSocket);
		 //  cp_start=strchr(end,C_ST_);
		 //  p=cp_start;
		 //  ++try_pack;
	  // }*/else{
   //        p=end+1;
		 //  ++try_pack;
	  // }
	   
	}
	//return true;
	

	if(err_no){
		PRINTLN("ERRIP:" << client.get_ip());
		//g_wong_count.replace();
		map<int,int>::iterator it=g_wong_count.find(client.nSocket);
		if(it!=g_wong_count.end())
		{
			//错误包到达一定数量 关闭链接
			if(it->second>=m_iwong_count)
			{
				return false;
			}
		}
		return true;
	}

	return true;
}

void EventTrigger::touchCloseEvent(const ANet& client)
{
	int result;
	PRINTLN("Close IP:"<< client.get_ip()<<" PORT"<<client.nSocket);
	lcScript.call(result,"OnClose_Socket","%d",client.nSocket);
}
